<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <meta name="keywords" content="Hexo Theme Redefine">
    
    <meta name="author" content="xiaoeryu">
    <!-- preconnect -->
    <link rel="preconnect" href="https://fonts.googleapis.com">
    <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>

    
    <!--- Seo Part-->
    
    <link rel="canonical" href="https://xiaoeeyu.github.io/2022/12/11/30-中断和异常的处理与抢占式多任务/"/>
    <meta name="robots" content="index,follow">
    <meta name="googlebot" content="index,follow">
    <meta name="revisit-after" content="1 days">
    
    
    
        
        <meta name="description" content="1. 中断和异常概述协同式任务切换不一定要通过一个专门的接口例程进行，也可以用一般的例程进行。">
<meta property="og:type" content="article">
<meta property="og:title" content="中断和异常的处理与抢占式多任务">
<meta property="og:url" content="https://xiaoeeyu.github.io/2022/12/11/30-%E4%B8%AD%E6%96%AD%E5%92%8C%E5%BC%82%E5%B8%B8%E7%9A%84%E5%A4%84%E7%90%86%E4%B8%8E%E6%8A%A2%E5%8D%A0%E5%BC%8F%E5%A4%9A%E4%BB%BB%E5%8A%A1/index.html">
<meta property="og:site_name" content="xiaoeryu">
<meta property="og:description" content="1. 中断和异常概述协同式任务切换不一定要通过一个专门的接口例程进行，也可以用一般的例程进行。">
<meta property="og:locale" content="zh_CN">
<meta property="og:image" content="https://xiaoeeyu.github.io/2022/12/11/30-%E4%B8%AD%E6%96%AD%E5%92%8C%E5%BC%82%E5%B8%B8%E7%9A%84%E5%A4%84%E7%90%86%E4%B8%8E%E6%8A%A2%E5%8D%A0%E5%BC%8F%E5%A4%9A%E4%BB%BB%E5%8A%A1/fe53f291cfd54bdb4ff39df4c2a88337.png">
<meta property="og:image" content="https://xiaoeeyu.github.io/2022/12/11/30-%E4%B8%AD%E6%96%AD%E5%92%8C%E5%BC%82%E5%B8%B8%E7%9A%84%E5%A4%84%E7%90%86%E4%B8%8E%E6%8A%A2%E5%8D%A0%E5%BC%8F%E5%A4%9A%E4%BB%BB%E5%8A%A1/0541841212d9120d7adc89707c464bc7.png">
<meta property="og:image" content="https://xiaoeeyu.github.io/2022/12/11/30-%E4%B8%AD%E6%96%AD%E5%92%8C%E5%BC%82%E5%B8%B8%E7%9A%84%E5%A4%84%E7%90%86%E4%B8%8E%E6%8A%A2%E5%8D%A0%E5%BC%8F%E5%A4%9A%E4%BB%BB%E5%8A%A1/e083d1c54d9b807af3a4d71568db31b6.png">
<meta property="og:image" content="https://xiaoeeyu.github.io/2022/12/11/30-%E4%B8%AD%E6%96%AD%E5%92%8C%E5%BC%82%E5%B8%B8%E7%9A%84%E5%A4%84%E7%90%86%E4%B8%8E%E6%8A%A2%E5%8D%A0%E5%BC%8F%E5%A4%9A%E4%BB%BB%E5%8A%A1/9f6e794666998a02b19d053418864147.png">
<meta property="og:image" content="https://xiaoeeyu.github.io/2022/12/11/30-%E4%B8%AD%E6%96%AD%E5%92%8C%E5%BC%82%E5%B8%B8%E7%9A%84%E5%A4%84%E7%90%86%E4%B8%8E%E6%8A%A2%E5%8D%A0%E5%BC%8F%E5%A4%9A%E4%BB%BB%E5%8A%A1/a1aab83b38172cd0c1405bb831af0706.png">
<meta property="og:image" content="https://xiaoeeyu.github.io/2022/12/11/30-%E4%B8%AD%E6%96%AD%E5%92%8C%E5%BC%82%E5%B8%B8%E7%9A%84%E5%A4%84%E7%90%86%E4%B8%8E%E6%8A%A2%E5%8D%A0%E5%BC%8F%E5%A4%9A%E4%BB%BB%E5%8A%A1/826b6014ebc1fb0f05fc99bdb31944d1.png">
<meta property="og:image" content="https://xiaoeeyu.github.io/2022/12/11/30-%E4%B8%AD%E6%96%AD%E5%92%8C%E5%BC%82%E5%B8%B8%E7%9A%84%E5%A4%84%E7%90%86%E4%B8%8E%E6%8A%A2%E5%8D%A0%E5%BC%8F%E5%A4%9A%E4%BB%BB%E5%8A%A1/70cbd9f6d7a234ea6667922d43c27f20.png">
<meta property="og:image" content="https://xiaoeeyu.github.io/2022/12/11/30-%E4%B8%AD%E6%96%AD%E5%92%8C%E5%BC%82%E5%B8%B8%E7%9A%84%E5%A4%84%E7%90%86%E4%B8%8E%E6%8A%A2%E5%8D%A0%E5%BC%8F%E5%A4%9A%E4%BB%BB%E5%8A%A1/05b1c6c1d0dcb160102e0248a536feca.png">
<meta property="og:image" content="https://xiaoeeyu.github.io/2022/12/11/30-%E4%B8%AD%E6%96%AD%E5%92%8C%E5%BC%82%E5%B8%B8%E7%9A%84%E5%A4%84%E7%90%86%E4%B8%8E%E6%8A%A2%E5%8D%A0%E5%BC%8F%E5%A4%9A%E4%BB%BB%E5%8A%A1/506f1a49cbf434b592d7810c41d99dfc.png">
<meta property="og:image" content="https://xiaoeeyu.github.io/2022/12/11/30-%E4%B8%AD%E6%96%AD%E5%92%8C%E5%BC%82%E5%B8%B8%E7%9A%84%E5%A4%84%E7%90%86%E4%B8%8E%E6%8A%A2%E5%8D%A0%E5%BC%8F%E5%A4%9A%E4%BB%BB%E5%8A%A1/7957d4bde64a8c498450b215e31de922.png">
<meta property="og:image" content="https://xiaoeeyu.github.io/2022/12/11/30-%E4%B8%AD%E6%96%AD%E5%92%8C%E5%BC%82%E5%B8%B8%E7%9A%84%E5%A4%84%E7%90%86%E4%B8%8E%E6%8A%A2%E5%8D%A0%E5%BC%8F%E5%A4%9A%E4%BB%BB%E5%8A%A1/f0ce0cd6d25a0616bf8bbf347dbf1802.png">
<meta property="og:image" content="https://xiaoeeyu.github.io/2022/12/11/30-%E4%B8%AD%E6%96%AD%E5%92%8C%E5%BC%82%E5%B8%B8%E7%9A%84%E5%A4%84%E7%90%86%E4%B8%8E%E6%8A%A2%E5%8D%A0%E5%BC%8F%E5%A4%9A%E4%BB%BB%E5%8A%A1/d24b99343349d21cb8e624e9d7860a1d.png">
<meta property="og:image" content="https://xiaoeeyu.github.io/2022/12/11/30-%E4%B8%AD%E6%96%AD%E5%92%8C%E5%BC%82%E5%B8%B8%E7%9A%84%E5%A4%84%E7%90%86%E4%B8%8E%E6%8A%A2%E5%8D%A0%E5%BC%8F%E5%A4%9A%E4%BB%BB%E5%8A%A1/b9132c903725144ad56a81ec7e391e95.png">
<meta property="og:image" content="https://xiaoeeyu.github.io/2022/12/11/30-%E4%B8%AD%E6%96%AD%E5%92%8C%E5%BC%82%E5%B8%B8%E7%9A%84%E5%A4%84%E7%90%86%E4%B8%8E%E6%8A%A2%E5%8D%A0%E5%BC%8F%E5%A4%9A%E4%BB%BB%E5%8A%A1/99bae412d7ff952cfc8225cb8b0a28ea.png">
<meta property="og:image" content="https://xiaoeeyu.github.io/2022/12/11/30-%E4%B8%AD%E6%96%AD%E5%92%8C%E5%BC%82%E5%B8%B8%E7%9A%84%E5%A4%84%E7%90%86%E4%B8%8E%E6%8A%A2%E5%8D%A0%E5%BC%8F%E5%A4%9A%E4%BB%BB%E5%8A%A1/0faf013194812787745b38e3d79ad29e.png">
<meta property="og:image" content="https://xiaoeeyu.github.io/2022/12/11/30-%E4%B8%AD%E6%96%AD%E5%92%8C%E5%BC%82%E5%B8%B8%E7%9A%84%E5%A4%84%E7%90%86%E4%B8%8E%E6%8A%A2%E5%8D%A0%E5%BC%8F%E5%A4%9A%E4%BB%BB%E5%8A%A1/bb3507b237ba7570270d16a6f6990d84.png">
<meta property="og:image" content="https://xiaoeeyu.github.io/2022/12/11/30-%E4%B8%AD%E6%96%AD%E5%92%8C%E5%BC%82%E5%B8%B8%E7%9A%84%E5%A4%84%E7%90%86%E4%B8%8E%E6%8A%A2%E5%8D%A0%E5%BC%8F%E5%A4%9A%E4%BB%BB%E5%8A%A1/8a32fa7cbcfac5aed5d3a2f92dcd4962.png">
<meta property="og:image" content="https://xiaoeeyu.github.io/2022/12/11/30-%E4%B8%AD%E6%96%AD%E5%92%8C%E5%BC%82%E5%B8%B8%E7%9A%84%E5%A4%84%E7%90%86%E4%B8%8E%E6%8A%A2%E5%8D%A0%E5%BC%8F%E5%A4%9A%E4%BB%BB%E5%8A%A1/1b3a44f5f57993fa3fde845ab5e753fe.png">
<meta property="og:image" content="https://xiaoeeyu.github.io/2022/12/11/30-%E4%B8%AD%E6%96%AD%E5%92%8C%E5%BC%82%E5%B8%B8%E7%9A%84%E5%A4%84%E7%90%86%E4%B8%8E%E6%8A%A2%E5%8D%A0%E5%BC%8F%E5%A4%9A%E4%BB%BB%E5%8A%A1/f91758bee251fd8220e7de9497bcc1d7.png">
<meta property="og:image" content="https://xiaoeeyu.github.io/2022/12/11/30-%E4%B8%AD%E6%96%AD%E5%92%8C%E5%BC%82%E5%B8%B8%E7%9A%84%E5%A4%84%E7%90%86%E4%B8%8E%E6%8A%A2%E5%8D%A0%E5%BC%8F%E5%A4%9A%E4%BB%BB%E5%8A%A1/511bc7af4ee3bcacd4ac5eae71ef3a8b.png">
<meta property="og:image" content="https://xiaoeeyu.github.io/2022/12/11/30-%E4%B8%AD%E6%96%AD%E5%92%8C%E5%BC%82%E5%B8%B8%E7%9A%84%E5%A4%84%E7%90%86%E4%B8%8E%E6%8A%A2%E5%8D%A0%E5%BC%8F%E5%A4%9A%E4%BB%BB%E5%8A%A1/13779e943bef875df248803639068b0e.png">
<meta property="og:image" content="https://xiaoeeyu.github.io/2022/12/11/30-%E4%B8%AD%E6%96%AD%E5%92%8C%E5%BC%82%E5%B8%B8%E7%9A%84%E5%A4%84%E7%90%86%E4%B8%8E%E6%8A%A2%E5%8D%A0%E5%BC%8F%E5%A4%9A%E4%BB%BB%E5%8A%A1/23d57fbce03a1e104a6cd035237449ad.png">
<meta property="og:image" content="https://xiaoeeyu.github.io/2022/12/11/30-%E4%B8%AD%E6%96%AD%E5%92%8C%E5%BC%82%E5%B8%B8%E7%9A%84%E5%A4%84%E7%90%86%E4%B8%8E%E6%8A%A2%E5%8D%A0%E5%BC%8F%E5%A4%9A%E4%BB%BB%E5%8A%A1/322fd7154dbaeccf68c9b55f409709b7.png">
<meta property="og:image" content="https://xiaoeeyu.github.io/2022/12/11/30-%E4%B8%AD%E6%96%AD%E5%92%8C%E5%BC%82%E5%B8%B8%E7%9A%84%E5%A4%84%E7%90%86%E4%B8%8E%E6%8A%A2%E5%8D%A0%E5%BC%8F%E5%A4%9A%E4%BB%BB%E5%8A%A1/36d0e5a120263624bae1c2858c3332db.png">
<meta property="og:image" content="https://xiaoeeyu.github.io/2022/12/11/30-%E4%B8%AD%E6%96%AD%E5%92%8C%E5%BC%82%E5%B8%B8%E7%9A%84%E5%A4%84%E7%90%86%E4%B8%8E%E6%8A%A2%E5%8D%A0%E5%BC%8F%E5%A4%9A%E4%BB%BB%E5%8A%A1/03e4ed8fdb2ef8b212b089f9594fcc49.png">
<meta property="og:image" content="https://xiaoeeyu.github.io/2022/12/11/30-%E4%B8%AD%E6%96%AD%E5%92%8C%E5%BC%82%E5%B8%B8%E7%9A%84%E5%A4%84%E7%90%86%E4%B8%8E%E6%8A%A2%E5%8D%A0%E5%BC%8F%E5%A4%9A%E4%BB%BB%E5%8A%A1/f2812cf72dc369391ac07c63b3f41e95.png">
<meta property="og:image" content="https://xiaoeeyu.github.io/2022/12/11/30-%E4%B8%AD%E6%96%AD%E5%92%8C%E5%BC%82%E5%B8%B8%E7%9A%84%E5%A4%84%E7%90%86%E4%B8%8E%E6%8A%A2%E5%8D%A0%E5%BC%8F%E5%A4%9A%E4%BB%BB%E5%8A%A1/8d8fc85f4918195b657b13bce9ecdb76.png">
<meta property="og:image" content="https://xiaoeeyu.github.io/2022/12/11/30-%E4%B8%AD%E6%96%AD%E5%92%8C%E5%BC%82%E5%B8%B8%E7%9A%84%E5%A4%84%E7%90%86%E4%B8%8E%E6%8A%A2%E5%8D%A0%E5%BC%8F%E5%A4%9A%E4%BB%BB%E5%8A%A1/6bbffc572736523b0dae80c2f7e4af88.png">
<meta property="og:image" content="https://xiaoeeyu.github.io/2022/12/11/30-%E4%B8%AD%E6%96%AD%E5%92%8C%E5%BC%82%E5%B8%B8%E7%9A%84%E5%A4%84%E7%90%86%E4%B8%8E%E6%8A%A2%E5%8D%A0%E5%BC%8F%E5%A4%9A%E4%BB%BB%E5%8A%A1/53ebd2ffd1f4494590783b20c4f37c65.png">
<meta property="og:image" content="https://xiaoeeyu.github.io/2022/12/11/30-%E4%B8%AD%E6%96%AD%E5%92%8C%E5%BC%82%E5%B8%B8%E7%9A%84%E5%A4%84%E7%90%86%E4%B8%8E%E6%8A%A2%E5%8D%A0%E5%BC%8F%E5%A4%9A%E4%BB%BB%E5%8A%A1/67c03f5323edfd9544c0235661096d39.png">
<meta property="og:image" content="https://xiaoeeyu.github.io/2022/12/11/30-%E4%B8%AD%E6%96%AD%E5%92%8C%E5%BC%82%E5%B8%B8%E7%9A%84%E5%A4%84%E7%90%86%E4%B8%8E%E6%8A%A2%E5%8D%A0%E5%BC%8F%E5%A4%9A%E4%BB%BB%E5%8A%A1/06739af9c2e734f283fc024ed041df76.png">
<meta property="og:image" content="https://xiaoeeyu.github.io/2022/12/11/30-%E4%B8%AD%E6%96%AD%E5%92%8C%E5%BC%82%E5%B8%B8%E7%9A%84%E5%A4%84%E7%90%86%E4%B8%8E%E6%8A%A2%E5%8D%A0%E5%BC%8F%E5%A4%9A%E4%BB%BB%E5%8A%A1/02c3a1acd2107868868cf3d50a36ffaa.png">
<meta property="og:image" content="https://xiaoeeyu.github.io/2022/12/11/30-%E4%B8%AD%E6%96%AD%E5%92%8C%E5%BC%82%E5%B8%B8%E7%9A%84%E5%A4%84%E7%90%86%E4%B8%8E%E6%8A%A2%E5%8D%A0%E5%BC%8F%E5%A4%9A%E4%BB%BB%E5%8A%A1/b98070cf32d38af1095d692179618875.png">
<meta property="og:image" content="https://xiaoeeyu.github.io/2022/12/11/30-%E4%B8%AD%E6%96%AD%E5%92%8C%E5%BC%82%E5%B8%B8%E7%9A%84%E5%A4%84%E7%90%86%E4%B8%8E%E6%8A%A2%E5%8D%A0%E5%BC%8F%E5%A4%9A%E4%BB%BB%E5%8A%A1/5332d252c92ab03ba05f620d2d165454.png">
<meta property="og:image" content="https://xiaoeeyu.github.io/2022/12/11/30-%E4%B8%AD%E6%96%AD%E5%92%8C%E5%BC%82%E5%B8%B8%E7%9A%84%E5%A4%84%E7%90%86%E4%B8%8E%E6%8A%A2%E5%8D%A0%E5%BC%8F%E5%A4%9A%E4%BB%BB%E5%8A%A1/7e6e29824e3d95591e20eeb190f3c945.png">
<meta property="og:image" content="https://xiaoeeyu.github.io/2022/12/11/30-%E4%B8%AD%E6%96%AD%E5%92%8C%E5%BC%82%E5%B8%B8%E7%9A%84%E5%A4%84%E7%90%86%E4%B8%8E%E6%8A%A2%E5%8D%A0%E5%BC%8F%E5%A4%9A%E4%BB%BB%E5%8A%A1/61a9d56175641a5edbf7407f56f60a6a.png">
<meta property="og:image" content="https://xiaoeeyu.github.io/2022/12/11/30-%E4%B8%AD%E6%96%AD%E5%92%8C%E5%BC%82%E5%B8%B8%E7%9A%84%E5%A4%84%E7%90%86%E4%B8%8E%E6%8A%A2%E5%8D%A0%E5%BC%8F%E5%A4%9A%E4%BB%BB%E5%8A%A1/5a7cfbe8d5a437a0aaf077939a037602.png">
<meta property="og:image" content="https://xiaoeeyu.github.io/2022/12/11/30-%E4%B8%AD%E6%96%AD%E5%92%8C%E5%BC%82%E5%B8%B8%E7%9A%84%E5%A4%84%E7%90%86%E4%B8%8E%E6%8A%A2%E5%8D%A0%E5%BC%8F%E5%A4%9A%E4%BB%BB%E5%8A%A1/b5657e47353d532e0cfe1989136f34ba.png">
<meta property="og:image" content="https://xiaoeeyu.github.io/2022/12/11/30-%E4%B8%AD%E6%96%AD%E5%92%8C%E5%BC%82%E5%B8%B8%E7%9A%84%E5%A4%84%E7%90%86%E4%B8%8E%E6%8A%A2%E5%8D%A0%E5%BC%8F%E5%A4%9A%E4%BB%BB%E5%8A%A1/image-20221113165929743.png">
<meta property="article:published_time" content="2022-12-11T14:48:00.000Z">
<meta property="article:modified_time" content="2023-10-03T05:00:20.683Z">
<meta property="article:author" content="xiaoeryu">
<meta property="article:tag" content="x86中断和异常">
<meta name="twitter:card" content="summary">
<meta name="twitter:image" content="https://xiaoeeyu.github.io/2022/12/11/30-%E4%B8%AD%E6%96%AD%E5%92%8C%E5%BC%82%E5%B8%B8%E7%9A%84%E5%A4%84%E7%90%86%E4%B8%8E%E6%8A%A2%E5%8D%A0%E5%BC%8F%E5%A4%9A%E4%BB%BB%E5%8A%A1/fe53f291cfd54bdb4ff39df4c2a88337.png">
    
    
    <!--- Icon Part-->
    <link rel="icon" type="image/png" href="/images/rabete.jpg" sizes="192x192">
    <link rel="apple-touch-icon" sizes="180x180" href="/images/rabete.jpg">
    <meta name="theme-color" content="#A31F34">
    <link rel="shortcut icon" href="/images/rabete.jpg">
    <!--- Page Info-->
    
    <title>
        
            中断和异常的处理与抢占式多任务 | xiaoeryu
        
    </title>

    
<link rel="stylesheet" href="/fonts/Chillax/chillax.css">


    <!--- Inject Part-->
    

    
<link rel="stylesheet" href="/css/style.css">


    
        
<link rel="stylesheet" href="/css/build/tailwind.css">

    

    
<link rel="stylesheet" href="/fonts/GeistMono/geist-mono.css">

    
<link rel="stylesheet" href="/fonts/Geist/geist.css">

    <!--- Font Part-->
    
    
    
    
    
    

    <script id="hexo-configurations">
    window.config = {"hostname":"xiaoeeyu.github.io","root":"/","language":"zh-CN","path":"search.xml"};
    window.theme = {"articles":{"style":{"font_size":"16px","line_height":1.5,"image_border_radius":"14px","image_alignment":"center","image_caption":false,"link_icon":true,"delete_mask":false,"title_alignment":"left","headings_top_spacing":{"h1":"3.2rem","h2":"2.4rem","h3":"1.9rem","h4":"1.6rem","h5":"1.4rem","h6":"1.3rem"}},"word_count":{"enable":true,"count":true,"min2read":true},"author_label":{"enable":true,"auto":false,"list":[]},"code_block":{"copy":true,"style":"mac","highlight_theme":{"light":"github","dark":"vs2015"},"font":{"enable":false,"family":null,"url":null}},"toc":{"enable":true,"max_depth":4,"number":false,"expand":true,"init_open":true},"copyright":{"enable":true,"default":"cc_by_nc_sa"},"lazyload":true,"pangu_js":false,"recommendation":{"enable":false,"title":"推荐阅读","limit":3,"mobile_limit":2,"placeholder":"/images/ball-0101.jpg","skip_dirs":[]}},"colors":{"primary":"#A31F34","secondary":null,"default_mode":"light"},"global":{"fonts":{"chinese":{"enable":false,"family":null,"url":null},"english":{"enable":false,"family":null,"url":null},"title":{"enable":false,"family":null,"url":null}},"content_max_width":"1000px","sidebar_width":"210px","hover":{"shadow":true,"scale":false},"scroll_progress":{"bar":false,"percentage":true},"website_counter":{"url":"https://busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js","enable":true,"site_pv":true,"site_uv":true,"post_pv":true},"single_page":true,"preloader":{"enable":false,"custom_message":null},"open_graph":true,"google_analytics":{"enable":false,"id":null}},"home_banner":{"enable":true,"style":"fixed","image":{"light":"/images/wallhaven-jxl31y.png","dark":"/images/wallhaven-o5762l.png"},"title":"XIAOERYU","subtitle":{"text":["明心见性，拨云见日","Don't wait, to create"],"hitokoto":{"enable":false,"show_author":false,"api":"https://v1.hitokoto.cn"},"typing_speed":100,"backing_speed":80,"starting_delay":500,"backing_delay":1500,"loop":true,"smart_backspace":true},"text_color":{"light":"#fff","dark":"#d1d1b6"},"text_style":{"title_size":"2.8rem","subtitle_size":"1.5rem","line_height":1.2},"custom_font":{"enable":false,"family":null,"url":null},"social_links":{"enable":true,"style":"default","links":{"github":"https://github.com/xiaoeeyu","instagram":null,"zhihu":null,"twitter":null,"email":"xiaoeryu@163.com"},"qrs":{"weixin":null}}},"plugins":{"feed":{"enable":false},"aplayer":{"enable":false,"type":"fixed","audios":[{"name":null,"artist":null,"url":null,"cover":null,"lrc":null}]},"mermaid":{"enable":false,"version":"9.3.0"}},"version":"2.8.2","navbar":{"auto_hide":false,"color":{"left":"#f78736","right":"#367df7","transparency":35},"width":{"home":"1200px","pages":"1000px"},"links":{"Home":{"path":"/","icon":"fa-regular fa-house"},"Archives":{"path":"/archives","icon":"fa-regular fa-archive"}},"search":{"enable":true,"preload":true}},"page_templates":{"friends_column":2,"tags_style":"blur"},"home":{"sidebar":{"enable":true,"position":"left","first_item":"menu","announcement":null,"show_on_mobile":true,"links":null},"article_date_format":"auto","excerpt_length":200,"categories":{"enable":true,"limit":3},"tags":{"enable":true,"limit":3}},"footerStart":"2022/8/17 11:45:14"};
    window.lang_ago = {"second":"%s 秒前","minute":"%s 分钟前","hour":"%s 小时前","day":"%s 天前","week":"%s 周前","month":"%s 个月前","year":"%s 年前"};
    window.data = {"masonry":false};
  </script>
    
    <!--- Fontawesome Part-->
    
<link rel="stylesheet" href="/fontawesome/fontawesome.min.css">

    
<link rel="stylesheet" href="/fontawesome/brands.min.css">

    
<link rel="stylesheet" href="/fontawesome/solid.min.css">

    
<link rel="stylesheet" href="/fontawesome/regular.min.css">

    
    
    
    
<meta name="generator" content="Hexo 6.3.0">
<style>.github-emoji { position: relative; display: inline-block; width: 1.2em; min-height: 1.2em; overflow: hidden; vertical-align: top; color: transparent; }  .github-emoji > span { position: relative; z-index: 10; }  .github-emoji img, .github-emoji .fancybox { margin: 0 !important; padding: 0 !important; border: none !important; outline: none !important; text-decoration: none !important; user-select: none !important; cursor: auto !important; }  .github-emoji img { height: 1.2em !important; width: 1.2em !important; position: absolute !important; left: 50% !important; top: 50% !important; transform: translate(-50%, -50%) !important; user-select: none !important; cursor: auto !important; } .github-emoji-fallback { color: inherit; } .github-emoji-fallback img { opacity: 0 !important; }</style>
</head>



<body>
	<div class="progress-bar-container">
	

	
	<span class="pjax-progress-bar"></span>
	<!--        <span class="swup-progress-icon">-->
	<!--            <i class="fa-solid fa-circle-notch fa-spin"></i>-->
	<!--        </span>-->
	
</div>

<main class="page-container" id="swup">

	

	<div class="main-content-container flex flex-col justify-between min-h-dvh">
		<div class="main-content-header">
			<header class="navbar-container px-6 md:px-12">
    <div class="navbar-content transition-navbar ">
        <div class="left">
            
                <a class="logo-image h-8 w-8 sm:w-10 sm:h-10 mr-3" href="/">
                    <img src="/images/rabete.jpg" class="w-full h-full rounded-sm">
                </a>
            
            <a class="logo-title" href="/">
                
                xiaoeryu
                
            </a>
        </div>

        <div class="right">
            <!-- PC -->
            <div class="desktop">
                <ul class="navbar-list">
                    
                        
                            

                            <li class="navbar-item">
                                <!-- Menu -->
                                <a class=""
                                   href="/"
                                        >
                                    <i class="fa-regular fa-house fa-fw"></i>
                                    首页
                                    
                                </a>

                                <!-- Submenu -->
                                
                            </li>
                    
                        
                            

                            <li class="navbar-item">
                                <!-- Menu -->
                                <a class=""
                                   href="/archives"
                                        >
                                    <i class="fa-regular fa-archive fa-fw"></i>
                                    归档
                                    
                                </a>

                                <!-- Submenu -->
                                
                            </li>
                    
                    
                        <li class="navbar-item search search-popup-trigger">
                            <i class="fa-solid fa-magnifying-glass"></i>
                        </li>
                    
                </ul>
            </div>
            <!-- Mobile -->
            <div class="mobile">
                
                    <div class="icon-item search search-popup-trigger"><i class="fa-solid fa-magnifying-glass"></i>
                    </div>
                
                <div class="icon-item navbar-bar">
                    <div class="navbar-bar-middle"></div>
                </div>
            </div>
        </div>
    </div>

    <!-- Mobile sheet -->
    <div class="navbar-drawer h-dvh w-full absolute top-0 left-0 bg-background-color flex flex-col justify-between">
        <ul class="drawer-navbar-list flex flex-col px-4 justify-center items-start">
            
                
                    

                    <li class="drawer-navbar-item text-base my-1.5 flex flex-col w-full">
                        
                        <a class="py-1.5 px-2 flex flex-row items-center justify-between gap-1 hover:!text-primary active:!text-primary text-2xl font-semibold group border-b border-border-color hover:border-primary w-full "
                           href="/"
                        >
                            <span>
                                首页
                            </span>
                            
                                <i class="fa-regular fa-house fa-sm fa-fw"></i>
                            
                        </a>
                        

                        
                    </li>
            
                
                    

                    <li class="drawer-navbar-item text-base my-1.5 flex flex-col w-full">
                        
                        <a class="py-1.5 px-2 flex flex-row items-center justify-between gap-1 hover:!text-primary active:!text-primary text-2xl font-semibold group border-b border-border-color hover:border-primary w-full "
                           href="/archives"
                        >
                            <span>
                                归档
                            </span>
                            
                                <i class="fa-regular fa-archive fa-sm fa-fw"></i>
                            
                        </a>
                        

                        
                    </li>
            

            
            
        </ul>

        <div class="statistics flex justify-around my-2.5">
    <a class="item tag-count-item flex flex-col justify-center items-center w-20" href="/tags">
        <div class="number text-2xl sm:text-xl text-second-text-color font-semibold">92</div>
        <div class="label text-third-text-color text-sm">标签</div>
    </a>
    <a class="item tag-count-item flex flex-col justify-center items-center w-20" href="/categories">
        <div class="number text-2xl sm:text-xl text-second-text-color font-semibold">14</div>
        <div class="label text-third-text-color text-sm">分类</div>
    </a>
    <a class="item tag-count-item flex flex-col justify-center items-center w-20" href="/archives">
        <div class="number text-2xl sm:text-xl text-second-text-color font-semibold">112</div>
        <div class="label text-third-text-color text-sm">文章</div>
    </a>
</div>
    </div>

    <div class="window-mask"></div>

</header>


		</div>

		<div class="main-content-body transition-fade-up">
			

			<div class="main-content">
				<div class="post-page-container flex relative justify-between box-border w-full h-full">
	<div class="article-content-container">

		<div class="article-title relative w-full">
			
			<div class="w-full flex items-center pt-6 justify-start">
				<h1 class="article-title-regular text-second-text-color tracking-tight text-4xl md:text-6xl font-semibold px-2 sm:px-6 md:px-8 py-3">中断和异常的处理与抢占式多任务</h1>
			</div>
			
		</div>

		
		<div class="article-header flex flex-row gap-2 items-center px-2 sm:px-6 md:px-8">
			<div class="avatar w-[46px] h-[46px] flex-shrink-0 rounded-medium border border-border-color p-[1px]">
				<img src="/images/rabete.jpg">
			</div>
			<div class="info flex flex-col justify-between">
				<div class="author flex items-center">
					<span class="name text-default-text-color text-lg font-semibold">xiaoeryu</span>
					
					<span class="author-label ml-1.5 text-xs px-2 py-0.5 rounded-small text-third-text-color border border-shadow-color-1">Lv5</span>
					
				</div>
				<div class="meta-info">
					<div class="article-meta-info">
    <span class="article-date article-meta-item">
        <i class="fa-regular fa-pen-fancy"></i>&nbsp;
        <span class="desktop">2022-12-11 22:48</span>
        <span class="mobile">2022-12-11 22:48</span>
        <span class="hover-info">创建</span>
    </span>
    
        <span class="article-date article-meta-item">
            <i class="fa-regular fa-wrench"></i>&nbsp;
            <span class="desktop">2023-10-03 13:20</span>
            <span class="mobile">2023-10-03 13:20</span>
            <span class="hover-info">更新</span>
        </span>
    

    
        <span class="article-categories article-meta-item">
            <i class="fa-regular fa-folders"></i>&nbsp;
            <ul>
                
                
                    
                        
                        <li>
                            <a href="/categories/X86%E6%B1%87%E7%BC%96%EF%BC%9A%E5%AE%9E%E6%A8%A1%E5%BC%8F%E5%88%B0%E4%BF%9D%E6%8A%A4%E6%A8%A1%E5%BC%8F/">X86汇编：实模式到保护模式</a>&nbsp;
                        </li>
                    
                    
                
            </ul>
        </span>
    
    
        <span class="article-tags article-meta-item">
            <i class="fa-regular fa-tags"></i>&nbsp;
            <ul>
                
                    <li>
                        <a href="/tags/x86%E4%B8%AD%E6%96%AD%E5%92%8C%E5%BC%82%E5%B8%B8/">x86中断和异常</a>&nbsp;
                    </li>
                
            </ul>
        </span>
    

    
    
    
    
        <span class="article-pv article-meta-item">
            <i class="fa-regular fa-eye"></i>&nbsp;<span id="busuanzi_value_page_pv"></span>
        </span>
    
</div>

				</div>
			</div>
		</div>
		

		


		<div class="article-content markdown-body px-2 sm:px-6 md:px-8 pb-8">
			<h2 id="1-中断和异常概述"><a href="#1-中断和异常概述" class="headerlink" title="1. 中断和异常概述"></a>1. 中断和异常概述</h2><p>协同式任务切换不一定要通过一个专门的接口例程进行，也可以用一般的例程进行。</p>
<span id="more"></span>

<img lazyload="" src="/images/loading.svg" data-src="/2022/12/11/30-%E4%B8%AD%E6%96%AD%E5%92%8C%E5%BC%82%E5%B8%B8%E7%9A%84%E5%A4%84%E7%90%86%E4%B8%8E%E6%8A%A2%E5%8D%A0%E5%BC%8F%E5%A4%9A%E4%BB%BB%E5%8A%A1/fe53f291cfd54bdb4ff39df4c2a88337.png" class="">
<p>用户任务通过调用门切换到内核的<strong>put_string</strong>例程执行，在内核任务返回用户任务之前可以进行任务切换，之后再通过<strong>retf</strong>返回用户任务执行。</p>
<img lazyload="" src="/images/loading.svg" data-src="/2022/12/11/30-%E4%B8%AD%E6%96%AD%E5%92%8C%E5%BC%82%E5%B8%B8%E7%9A%84%E5%A4%84%E7%90%86%E4%B8%8E%E6%8A%A2%E5%8D%A0%E5%BC%8F%E5%A4%9A%E4%BB%BB%E5%8A%A1/0541841212d9120d7adc89707c464bc7.png" class="">

<ul>
<li>硬件中断信号，<mark>NMI</mark>是不可屏蔽中断、<mark>INTR</mark>是来自硬件中断引脚的可屏蔽中断。随机产生，与处理器是异步的。</li>
<li>软件中断，<mark>INT N</mark>是在软件内部主动引发的中断。</li>
<li>处理异常中断（Exceptions），是处理器内部产生的中断，表示处理器执行时产生了错误的状况。比如当处理器执行一条非法指令或者因条件不具备指令不能正常执行时将会引发这种类型的中断。如<mark>div指令</mark>中<mark>除数是0</mark>的情况。<img lazyload="" src="/images/loading.svg" data-src="/2022/12/11/30-%E4%B8%AD%E6%96%AD%E5%92%8C%E5%BC%82%E5%B8%B8%E7%9A%84%E5%A4%84%E7%90%86%E4%B8%8E%E6%8A%A2%E5%8D%A0%E5%BC%8F%E5%A4%9A%E4%BB%BB%E5%8A%A1/e083d1c54d9b807af3a4d71568db31b6.png" class="">
终端和异常<img lazyload="" src="/images/loading.svg" data-src="/2022/12/11/30-%E4%B8%AD%E6%96%AD%E5%92%8C%E5%BC%82%E5%B8%B8%E7%9A%84%E5%A4%84%E7%90%86%E4%B8%8E%E6%8A%A2%E5%8D%A0%E5%BC%8F%E5%A4%9A%E4%BB%BB%E5%8A%A1/9f6e794666998a02b19d053418864147.png" class="">
按照异常的产生原因分类：<ol>
<li>指令执行异常：处理器在执行指令时检测到程序的错误并由此而引发的异常</li>
<li>程序调试异常：供调试器使用，由<mark>INTO、INT3</mark>主动发起。用来检查特定的机器状态是否出现。<mark>INTO</mark>检查标志寄存器的<mark>OF=1</mark>（溢出标志位）则执行指令引发异常中断。<strong>INT3</strong>指令由调试器单步执行使用。</li>
<li>机器检查异常：和处理器架构有关，如在奔腾4、P6处理器家族上就实现了机器检查架构，用这种异常检测与硬件有关的总线错误、奇偶校验错误、高速缓存错误等等。</li>
</ol>
</li>
</ul>
<p>根据异常的性质和严重性分类：</p>
<img lazyload="" src="/images/loading.svg" data-src="/2022/12/11/30-%E4%B8%AD%E6%96%AD%E5%92%8C%E5%BC%82%E5%B8%B8%E7%9A%84%E5%A4%84%E7%90%86%E4%B8%8E%E6%8A%A2%E5%8D%A0%E5%BC%8F%E5%A4%9A%E4%BB%BB%E5%8A%A1/a1aab83b38172cd0c1405bb831af0706.png" class="">

<ol>
<li>故障（Faults）：通常可以纠正，如缺页异常。中断程序返回的是当前指令。</li>
<li>陷阱（Traps）：通常是在执行了截获陷阱条件的指令之后立即产生，通常用于调试<mark>INT3、INTO</mark>。中断程序返回的是当前指令的下一条指令。</li>
<li>终止（Aborts）：通常标志最严重的错误，如硬件错误、系统表错误（如GDT、LDT数据不一致、无效、错误），这类异常一般无法精确的报告引起错误的指令的位置。发生时程序和错误都不可能重新启动，双重异常（当处理器发生异常时，在转入异常执行时又发生了另一个异常）如中断向量号18，<mark>INT 0x18</mark>。</li>
</ol>
<p>对于某些异常来说，处理器再转入异常处理程序之前，会在栈中压入一个称为错误代码的数值，这样可以帮助诊断异常产生的位置和原因。</p>
<h2 id="02-保护模式下中断和异常的向量分配"><a href="#02-保护模式下中断和异常的向量分配" class="headerlink" title="02. 保护模式下中断和异常的向量分配"></a>02. 保护模式下中断和异常的向量分配</h2><p>终端和异常的编号叫做中断向量。</p>
<img lazyload="" src="/images/loading.svg" data-src="/2022/12/11/30-%E4%B8%AD%E6%96%AD%E5%92%8C%E5%BC%82%E5%B8%B8%E7%9A%84%E5%A4%84%E7%90%86%E4%B8%8E%E6%8A%A2%E5%8D%A0%E5%BC%8F%E5%A4%9A%E4%BB%BB%E5%8A%A1/826b6014ebc1fb0f05fc99bdb31944d1.png" class="">
<p>其中错误代码是在中断发生时，在进入中断处理程序之前压在栈中的错误代码。</p>
<h2 id="03-中断描述符、中断门和陷阱门"><a href="#03-中断描述符、中断门和陷阱门" class="headerlink" title="03. 中断描述符、中断门和陷阱门"></a>03. 中断描述符、中断门和陷阱门</h2><p>实模式下的中断向量表：</p>
<img lazyload="" src="/images/loading.svg" data-src="/2022/12/11/30-%E4%B8%AD%E6%96%AD%E5%92%8C%E5%BC%82%E5%B8%B8%E7%9A%84%E5%A4%84%E7%90%86%E4%B8%8E%E6%8A%A2%E5%8D%A0%E5%BC%8F%E5%A4%9A%E4%BB%BB%E5%8A%A1/70cbd9f6d7a234ea6667922d43c27f20.png" class="">
<p>中断发生时，处理器要么自发产生一个中断向量、要么从软中断指令的操作数到中断向量、或者从从外部的中断控制器取得一个中断向量。将该向量作为索引访问中断向量表<strong>IVT</strong>，具体做法是将中断向量乘以4作为偏移量访问<strong>IVT</strong>，从中取得中断处理过程的段地址和偏移地址，并转到那里执行。</p>
<p>保护模式下：使用中断描述符表<strong>IDT</strong>（Interrupt Descriptor Table），保存和中断处理过程相关的描述符，包括中断门、陷阱门、任务门，门是特殊的描述符。</p>
<p><mark>中断门</mark>描述符用来描述中断处理过程。</p>
<img lazyload="" src="/images/loading.svg" data-src="/2022/12/11/30-%E4%B8%AD%E6%96%AD%E5%92%8C%E5%BC%82%E5%B8%B8%E7%9A%84%E5%A4%84%E7%90%86%E4%B8%8E%E6%8A%A2%E5%8D%A0%E5%BC%8F%E5%A4%9A%E4%BB%BB%E5%8A%A1/05b1c6c1d0dcb160102e0248a536feca.png" class="">
<p><mark>陷阱门</mark>描述符用来描述陷阱中断的处理过程。</p>
<img lazyload="" src="/images/loading.svg" data-src="/2022/12/11/30-%E4%B8%AD%E6%96%AD%E5%92%8C%E5%BC%82%E5%B8%B8%E7%9A%84%E5%A4%84%E7%90%86%E4%B8%8E%E6%8A%A2%E5%8D%A0%E5%BC%8F%E5%A4%9A%E4%BB%BB%E5%8A%A1/506f1a49cbf434b592d7810c41d99dfc.png" class="">
<p>任务门，32位处理器支持，若<strong>IDT</strong>中描述的是一个任务门，则执行的是一个任务切换。在64位处理器中既不支持硬件切换也不支持任务门。</p>
<p>实模式下的中断向量表<strong>IVT</strong>只能位于内存的最低端。保护模式下的中断描述符表<strong>IDT</strong>可以位于内存的任何位置。</p>
<img lazyload="" src="/images/loading.svg" data-src="/2022/12/11/30-%E4%B8%AD%E6%96%AD%E5%92%8C%E5%BC%82%E5%B8%B8%E7%9A%84%E5%A4%84%E7%90%86%E4%B8%8E%E6%8A%A2%E5%8D%A0%E5%BC%8F%E5%A4%9A%E4%BB%BB%E5%8A%A1/7957d4bde64a8c498450b215e31de922.png" class="">
<p><strong>IDT</strong>的第一个描述符，即<mark>0号槽位</mark>也是有效的。</p>
<img lazyload="" src="/images/loading.svg" data-src="/2022/12/11/30-%E4%B8%AD%E6%96%AD%E5%92%8C%E5%BC%82%E5%B8%B8%E7%9A%84%E5%A4%84%E7%90%86%E4%B8%8E%E6%8A%A2%E5%8D%A0%E5%BC%8F%E5%A4%9A%E4%BB%BB%E5%8A%A1/f0ce0cd6d25a0616bf8bbf347dbf1802.png" class="">

<ul>
<li>处理器用中断向量乘以8得到表内偏移，联合<strong>IDTR</strong>内的<strong>IDT</strong>基地址去访问内存；</li>
<li>从中取得<strong>中断门</strong>或<strong>陷阱门</strong>描述符；</li>
<li>在描述符中有中断处理过程的<strong>代码段选择子</strong>和<strong>段内偏移量</strong>；</li>
<li>取决于代码段选择子的<strong>TI位</strong>，去<strong>GDT</strong>或<strong>LDT</strong>中取得目标代码段的描述符；</li>
<li>从目标代码段的描述符中取得目标代码段的段基地址；</li>
<li>将<strong>段基地址</strong>和<strong>偏移量</strong>相加得到中断处理过程的的线性地址，从而转移执行。</li>
</ul>
<p>使用中断向量访问<strong>IDT</strong>时，中断向量超过<strong>IDT</strong>界限值时，就会产生常规保护异常**#GP**。</p>
<h2 id="04-本章程序介绍"><a href="#04-本章程序介绍" class="headerlink" title="04. 本章程序介绍"></a>04. 本章程序介绍</h2><p>引导程序：<mark>c13_mbr0.asm</mark></p>
<ol>
<li>取出<strong>GDT</strong>所在线性基地址</li>
<li>创建本程序相关描述符，接着使用<strong>cli</strong>指令关闭中断响应</li>
<li>进入保护模式</li>
<li>加载内核代码到内存中</li>
<li>创建内核相关的描述符</li>
<li>跳转执行内核</li>
</ol>
<p>内核程序：<mark>c30_core0.asm</mark></p>
<ol>
<li>创建各个段的选择子常量和<strong>IDT</strong>线性地址</li>
<li>内核头部段</li>
<li>内核公共例程段，除了之前创建的相关例程，本章增加了几个和中断相关的例程</li>
<li>内核核心数据段，各种数据</li>
<li>内核核心代码，改变了内核入口点<strong>start</strong>的程序。</li>
</ol>
<p>用户程序0：<mark>c30_app0.asm</mark><br>其他不变，死循环打印<mark>，，，，，，</mark></p>
<p>用户程序1：<mark>c30_app1.asm</mark><br>其他不变，死循环打印<mark>cccccc</mark></p>
<h2 id="05-创建并安装全部的256个中断门"><a href="#05-创建并安装全部的256个中断门" class="headerlink" title="05. 创建并安装全部的256个中断门"></a>05. 创建并安装全部的256个中断门</h2><p>在进入内核<mark>start</mark>之后，准备创建内核任务、用户任务并进行任务切换，在此之前需要准备好保护模式下的中断系统。</p>
<p>中断或异常发生时，并不是直接调用中断或异常处理程序，而是用中断向量先到中断描述符中寻找对应的中断描述符，即中断门或陷阱门，之后从中断门或陷阱门中间接找到中断处理过程。意味着必须为这个通用的中断处理过程创建中断门或陷阱门，并安装在中断描述符表<mark>IDT</mark>中。</p>
<p>创建中断门代码如下：</p>
<pre><code class="assembly">    ;前20个向量是处理器异常使用的
    mov eax,general_exception_handler  ;门代码在段内偏移地址
    mov bx,sys_routine_seg_sel         ;门代码所在段的选择子
    mov cx,0x8e00                      ;32位中断门，0特权级
    call sys_routine_seg_sel:make_gate_descriptor
</code></pre>
<p>中断门属性值<mark>8E00</mark>：</p>
<img lazyload="" src="/images/loading.svg" data-src="/2022/12/11/30-%E4%B8%AD%E6%96%AD%E5%92%8C%E5%BC%82%E5%B8%B8%E7%9A%84%E5%A4%84%E7%90%86%E4%B8%8E%E6%8A%A2%E5%8D%A0%E5%BC%8F%E5%A4%9A%E4%BB%BB%E5%8A%A1/d24b99343349d21cb8e624e9d7860a1d.png" class="">
<p>创建好之后需要安装在中断描述符表<strong>IDT</strong>中，<strong>IDT</strong>现在还没有创建，创建<strong>IDT</strong>就是指定表的起始线性基地址，并从这个地址安装中断门和陷阱门就可以了。</p>
<p>目前系统内存布局：</p>
<img lazyload="" src="/images/loading.svg" data-src="/2022/12/11/30-%E4%B8%AD%E6%96%AD%E5%92%8C%E5%BC%82%E5%B8%B8%E7%9A%84%E5%A4%84%E7%90%86%E4%B8%8E%E6%8A%A2%E5%8D%A0%E5%BC%8F%E5%A4%9A%E4%BB%BB%E5%8A%A1/b9132c903725144ad56a81ec7e391e95.png" class="">

<p>依次安装中断门或陷阱门：前20个中断门指向通用处理过程<strong>general_exception_handler</strong>。</p>
<pre><code class="assembly">    mov ebx,idt_linear_address         ;中断描述符表的线性地址
    xor esi,esi
.idt0:
    mov [es:ebx+esi*8],eax				;基址变址寻址
    mov [es:ebx+esi*8+4],edx
    inc esi
    cmp esi,19                         ;安装前20个异常中断处理过程
    jle .idt0
</code></pre>
<p>之后安装通过的中断门：后236个中断门都指向同一个中断处理程序<strong>general_interrupt_handler</strong>。</p>
<pre><code class="assembly">    ;其余为保留或硬件使用的中断向量
    mov eax,general_interrupt_handler  ;门代码在段内偏移地址
    mov bx,sys_routine_seg_sel         ;门代码所在段的选择子
    mov cx,0x8e00                      ;32位中断门，0特权级
    call sys_routine_seg_sel:make_gate_descriptor
    
    mov ebx,idt_linear_address         ;中断描述符表的线性地址
.idt1:
    mov [es:ebx+esi*8],eax
    mov [es:ebx+esi*8+4],edx
    inc esi
    cmp esi,255                        ;安装普通的中断处理过程
    jle .idt1
</code></pre>
<h2 id="06-为实时时钟中断创建和安装中断门"><a href="#06-为实时时钟中断创建和安装中断门" class="headerlink" title="06. 为实时时钟中断创建和安装中断门"></a>06. 为实时时钟中断创建和安装中断门</h2><p>使用实时时钟中断，默认中断号<strong>0x70</strong>，当发生<strong>0x70</strong>号中断时并不是执行一个通用的中断过程，而是执行它自己的中断处理过程<strong>rtm_0x70_interrupt_handle</strong>。</p>
<p>现在需要创建<strong>0x70</strong>号中断的中断门，并安装在中断描述符表中，用来替换原来的通用中断门。</p>
<pre><code class="assembly">    ;设置实时时钟中断处理过程
    mov eax,rtm_0x70_interrupt_handle  ;门代码在段内偏移地址
    mov bx,sys_routine_seg_sel         ;门代码所在段的选择子
    mov cx,0x8e00                      ;32位中断门，0特权级
    call sys_routine_seg_sel:make_gate_descriptor
    
    mov ebx,idt_linear_address         ;中断描述符表的线性地址
    mov [es:ebx+0x70*8],eax
    mov [es:ebx+0x70*8+4],edx
</code></pre>
<h2 id="07-加载中断描述符表寄存器IDTR"><a href="#07-加载中断描述符表寄存器IDTR" class="headerlink" title="07. 加载中断描述符表寄存器IDTR"></a>07. 加载中断描述符表寄存器IDTR</h2><p>接上一节，现在已经在中断描述符表中安装了256个中断门，除了<strong>0x70</strong>号中断，其它都指向默认的中断或异常处理程序。</p>
<p>当中断发生时，处理器如何找到中断描述符表呢？处理器中有一个中断描述符表寄存器<strong>IDTR</strong>，保存着中断描述符表<strong>IDT</strong>的线性基地址以及长度。现在应该将<strong>IDT</strong>的基地址和界限值加载到<strong>IDTR</strong>中。</p>
<img lazyload="" src="/images/loading.svg" data-src="/2022/12/11/30-%E4%B8%AD%E6%96%AD%E5%92%8C%E5%BC%82%E5%B8%B8%E7%9A%84%E5%A4%84%E7%90%86%E4%B8%8E%E6%8A%A2%E5%8D%A0%E5%BC%8F%E5%A4%9A%E4%BB%BB%E5%8A%A1/99bae412d7ff952cfc8225cb8b0a28ea.png" class="">
<p>偏移为<em>m</em>的地方开辟出6个字节的空间。前2个字节保存<strong>IDT</strong>的界限值，后4字节保存着<strong>IDT</strong>的线性基地址。执行此条指令时，处理器用段寄存器中的线性基地址加上指令中的<strong>偏移m</strong>构成物理地址访问内存取出这6个字节。然后传送到处理器内部的<strong>IDTR</strong>寄存器中。该指令在实模式下也能执行。</p>
<p>开机时，<strong>IDTR</strong>中基地址被初始化为<strong>0x00000000</strong>，界限值被初始化为<strong>0xFFFF</strong>。<strong>lidt</strong>指令不影响任何标志位。代码如下：</p>
<pre><code class="assembly">    ;准备开放中断
    mov word [pidt],256*8-1            ;IDT的界限
    mov dword [pidt+2],idt_linear_address
    lidt [pidt]                        ;加载中断描述符表寄存器IDTR
</code></pre>
<h2 id="08-重新设置8259A主片的中断向量"><a href="#08-重新设置8259A主片的中断向量" class="headerlink" title="08. 重新设置8259A主片的中断向量"></a>08. 重新设置8259A主片的中断向量</h2><p>接上一节，理论上此时就可以开放中断，对到来的中断进行处理。但是还有一个问题，若中断控制器芯片还是8259A，就需要对其重新初始化。</p>
<p><strong>BIOS</strong>会将<strong>8259A</strong>主片中断号设置为如下，基本输入输出系统会将从片中段号设置为如下：</p>
<img lazyload="" src="/images/loading.svg" data-src="/2022/12/11/30-%E4%B8%AD%E6%96%AD%E5%92%8C%E5%BC%82%E5%B8%B8%E7%9A%84%E5%A4%84%E7%90%86%E4%B8%8E%E6%8A%A2%E5%8D%A0%E5%BC%8F%E5%A4%9A%E4%BB%BB%E5%8A%A1/0faf013194812787745b38e3d79ad29e.png" class="">
<p>由于主片中断向量和异常的中断向量冲突，所以需要重新初始化中断向量。</p>
<img lazyload="" src="/images/loading.svg" data-src="/2022/12/11/30-%E4%B8%AD%E6%96%AD%E5%92%8C%E5%BC%82%E5%B8%B8%E7%9A%84%E5%A4%84%E7%90%86%E4%B8%8E%E6%8A%A2%E5%8D%A0%E5%BC%8F%E5%A4%9A%E4%BB%BB%E5%8A%A1/bb3507b237ba7570270d16a6f6990d84.png" class="">
<p>修改为后面的中断向量：</p>
<img lazyload="" src="/images/loading.svg" data-src="/2022/12/11/30-%E4%B8%AD%E6%96%AD%E5%92%8C%E5%BC%82%E5%B8%B8%E7%9A%84%E5%A4%84%E7%90%86%E4%B8%8E%E6%8A%A2%E5%8D%A0%E5%BC%8F%E5%A4%9A%E4%BB%BB%E5%8A%A1/8a32fa7cbcfac5aed5d3a2f92dcd4962.png" class="">

<p>对<strong>8259A</strong>编程需要使用初始化命令字<strong>ICW</strong>。共4个，都是单字节命令，不是单独发送的，而是按顺序全部发送一遍，<strong>ICW1~ICW4</strong>，发送哪个取决于<strong>ICW1</strong>、<strong>ICW2</strong>的内容，可能<strong>ICW3</strong>、<strong>ICW4</strong>不需要发送。</p>
<img lazyload="" src="/images/loading.svg" data-src="/2022/12/11/30-%E4%B8%AD%E6%96%AD%E5%92%8C%E5%BC%82%E5%B8%B8%E7%9A%84%E5%A4%84%E7%90%86%E4%B8%8E%E6%8A%A2%E5%8D%A0%E5%BC%8F%E5%A4%9A%E4%BB%BB%E5%8A%A1/1b3a44f5f57993fa3fde845ab5e753fe.png" class="">
<p>对于主片来说先向<strong>0x20</strong>号端口发送<strong>ICW1</strong>，对于从片来说要向<strong>0xA0</strong>号端口发送<strong>ICW1</strong>，<strong>ICW1</strong>是一个标志，每次<strong>8259A</strong>芯片接收到<strong>ICW1</strong>表示一个新的初始化过程开始了。</p>
<p>从<strong>0x20、0xA0</strong>接收到<strong>ICW1</strong>后，<strong>8259A</strong>期待从<strong>0x21、0xA0</strong>接收<strong>ICW2</strong>，后续是否期待<strong>ICW3、ICW4</strong>要看<strong>ICW1</strong>的内容。<strong>ICW1</strong>发送给<strong>0x20、0xA0</strong>号端口作为标志，之后<strong>ICW2、ICW3、ICW4</strong>会发送给<strong>0x21、0xA1</strong>号端口。</p>
<p><mark>ICW1</mark>：</p>
<img lazyload="" src="/images/loading.svg" data-src="/2022/12/11/30-%E4%B8%AD%E6%96%AD%E5%92%8C%E5%BC%82%E5%B8%B8%E7%9A%84%E5%A4%84%E7%90%86%E4%B8%8E%E6%8A%A2%E5%8D%A0%E5%BC%8F%E5%A4%9A%E4%BB%BB%E5%8A%A1/f91758bee251fd8220e7de9497bcc1d7.png" class="">

<p><mark>ICW2</mark>：</p>
<img lazyload="" src="/images/loading.svg" data-src="/2022/12/11/30-%E4%B8%AD%E6%96%AD%E5%92%8C%E5%BC%82%E5%B8%B8%E7%9A%84%E5%A4%84%E7%90%86%E4%B8%8E%E6%8A%A2%E5%8D%A0%E5%BC%8F%E5%A4%9A%E4%BB%BB%E5%8A%A1/511bc7af4ee3bcacd4ac5eae71ef3a8b.png" class="">

<p><mark>ICW3</mark>：</p>
<img lazyload="" src="/images/loading.svg" data-src="/2022/12/11/30-%E4%B8%AD%E6%96%AD%E5%92%8C%E5%BC%82%E5%B8%B8%E7%9A%84%E5%A4%84%E7%90%86%E4%B8%8E%E6%8A%A2%E5%8D%A0%E5%BC%8F%E5%A4%9A%E4%BB%BB%E5%8A%A1/13779e943bef875df248803639068b0e.png" class="">

<p><mark>ICW4</mark>：</p>
<img lazyload="" src="/images/loading.svg" data-src="/2022/12/11/30-%E4%B8%AD%E6%96%AD%E5%92%8C%E5%BC%82%E5%B8%B8%E7%9A%84%E5%A4%84%E7%90%86%E4%B8%8E%E6%8A%A2%E5%8D%A0%E5%BC%8F%E5%A4%9A%E4%BB%BB%E5%8A%A1/23d57fbce03a1e104a6cd035237449ad.png" class="">

<p>代码如下：</p>
<pre><code class="assembly">    ;设置8259A中断控制器
    mov al,0x11
    out 0x20,al                        ;ICW1：边沿触发/级联方式
    mov al,0x20
    out 0x21,al                        ;ICW2:起始中断向量
    mov al,0x04
    out 0x21,al                        ;ICW3:从片级联到IR2
    mov al,0x01
    out 0x21,al                        ;ICW4:非总线缓冲，全嵌套，正常EOI
    
    mov al,0x11
    out 0xa0,al                        ;ICW1：边沿触发/级联方式
    mov al,0x70
    out 0xa1,al                        ;ICW2:起始中断向量
    mov al,0x04
    out 0xa1,al                        ;ICW3:从片级联到IR2
    mov al,0x01
    out 0xa1,al                        ;ICW4:非总线缓冲，全嵌套，正常EOI
</code></pre>
<p>之后设置和时钟中断相关的硬件：</p>
<pre><code class="assembly">    ;设置和时钟中断相关的硬件
    mov al,0x0b			;RTC寄存器B
    or al,0x80          ;阻断NMI
    out 0x70,al
    mov al,0x12         ;设置寄存器B，禁止周期性中断，开放更
    out 0x71,al         ;新结束后中断，BCD码，24小时制
    
    in al,0xa1          ;读8259从片的IMR寄存器
    and al,0xfe         ;清除bit 0(此位连接RTC)
    out 0xa1,al         ;写回此寄存器
    
    mov al,0x0c
    out 0x70,al
    in al,0x71          ;读RTC寄存器C，复位未决的中断状态
</code></pre>
<h2 id="09-中断和异常发生似的特权级检查"><a href="#09-中断和异常发生似的特权级检查" class="headerlink" title="09. 中断和异常发生似的特权级检查"></a>09. 中断和异常发生似的特权级检查</h2><p>接上一节，目前中断描述符表已经创建，在这个表中，所有与中断、异常相关的描述符已经安装完毕。包括<mark>0x70号中断</mark>，其中断门已经安装完毕，指向其自己的中断处理过程。</p>
<p>接下来开中断，讲标志寄存器<mark>IF</mark>位置1，那么中断就可以随时进来。</p>
<img lazyload="" src="/images/loading.svg" data-src="/2022/12/11/30-%E4%B8%AD%E6%96%AD%E5%92%8C%E5%BC%82%E5%B8%B8%E7%9A%84%E5%A4%84%E7%90%86%E4%B8%8E%E6%8A%A2%E5%8D%A0%E5%BC%8F%E5%A4%9A%E4%BB%BB%E5%8A%A1/322fd7154dbaeccf68c9b55f409709b7.png" class="">
<p>当中断发生时，处理器从软中断指令、或中断控制器芯片取得中断向量。用这个向量从中断描述符表<strong>IDT</strong>中取出中断门、陷阱门、任务门，但是中断向量只是一个代表中断号码的数字，没有表指示器、<strong>RPL</strong>字段，所以中断和异常发生时不检查<strong>RPL</strong>字段；</p>
<img lazyload="" src="/images/loading.svg" data-src="/2022/12/11/30-%E4%B8%AD%E6%96%AD%E5%92%8C%E5%BC%82%E5%B8%B8%E7%9A%84%E5%A4%84%E7%90%86%E4%B8%8E%E6%8A%A2%E5%8D%A0%E5%BC%8F%E5%A4%9A%E4%BB%BB%E5%8A%A1/36d0e5a120263624bae1c2858c3332db.png" class="">
<img lazyload="" src="/images/loading.svg" data-src="/2022/12/11/30-%E4%B8%AD%E6%96%AD%E5%92%8C%E5%BC%82%E5%B8%B8%E7%9A%84%E5%A4%84%E7%90%86%E4%B8%8E%E6%8A%A2%E5%8D%A0%E5%BC%8F%E5%A4%9A%E4%BB%BB%E5%8A%A1/03e4ed8fdb2ef8b212b089f9594fcc49.png" class="">
<img lazyload="" src="/images/loading.svg" data-src="/2022/12/11/30-%E4%B8%AD%E6%96%AD%E5%92%8C%E5%BC%82%E5%B8%B8%E7%9A%84%E5%A4%84%E7%90%86%E4%B8%8E%E6%8A%A2%E5%8D%A0%E5%BC%8F%E5%A4%9A%E4%BB%BB%E5%8A%A1/f2812cf72dc369391ac07c63b3f41e95.png" class="">


<h2 id="10-中断和异常发生时的栈切换过程"><a href="#10-中断和异常发生时的栈切换过程" class="headerlink" title="10. 中断和异常发生时的栈切换过程"></a>10. 中断和异常发生时的栈切换过程</h2><p>当中断发生时，处理器使用中断向量乘以8，到<strong>IDTR</strong>指定的中断描述符表<strong>IDT</strong>中取出一个描述符；</p>
<p>去除的描述符可能是中断门、陷阱门和任务门，中断门、陷阱门会转去执行中断处理程序，任务门会进行一个任务切换，本章并不是使用这种方式进行任务切换。</p>
<img lazyload="" src="/images/loading.svg" data-src="/2022/12/11/30-%E4%B8%AD%E6%96%AD%E5%92%8C%E5%BC%82%E5%B8%B8%E7%9A%84%E5%A4%84%E7%90%86%E4%B8%8E%E6%8A%A2%E5%8D%A0%E5%BC%8F%E5%A4%9A%E4%BB%BB%E5%8A%A1/8d8fc85f4918195b657b13bce9ecdb76.png" class="">

<ol>
<li>若目标代码段的特权级等于当前代码段的特权级，则使用当前代码段的栈，即中断和异常发生前正在使用的栈。</li>
<li>若目标代码段的特权级大于当前代码段的特权级，则处理器会切换到目标代码段的栈，那么这个新栈来自于当前任务的<strong>TSS</strong>中。从中选取一个和目标代码段相同特权级的栈。<img lazyload="" src="/images/loading.svg" data-src="/2022/12/11/30-%E4%B8%AD%E6%96%AD%E5%92%8C%E5%BC%82%E5%B8%B8%E7%9A%84%E5%A4%84%E7%90%86%E4%B8%8E%E6%8A%A2%E5%8D%A0%E5%BC%8F%E5%A4%9A%E4%BB%BB%E5%8A%A1/6bbffc572736523b0dae80c2f7e4af88.png" class="">
当中断或异常发生时，若当前特权级<strong>CPL</strong>和目标代码段特权级<strong>DPL</strong>不同，则系统中必须至少存在一个任务。<img lazyload="" src="/images/loading.svg" data-src="/2022/12/11/30-%E4%B8%AD%E6%96%AD%E5%92%8C%E5%BC%82%E5%B8%B8%E7%9A%84%E5%A4%84%E7%90%86%E4%B8%8E%E6%8A%A2%E5%8D%A0%E5%BC%8F%E5%A4%9A%E4%BB%BB%E5%8A%A1/53ebd2ffd1f4494590783b20c4f37c65.png" class=""></li>
</ol>
<ul>
<li>当前任务如上，若当前正在<strong>代码段2</strong>执行，则发生中断或异常，则切换到<strong>代码段1</strong>执行，且不需要切换栈。</li>
<li>若当前正在<strong>代码段3</strong>执行，则发生中断或异常，则切换到<strong>代码段1</strong>执行，此时需要切换栈</li>
</ul>
<img lazyload="" src="/images/loading.svg" data-src="/2022/12/11/30-%E4%B8%AD%E6%96%AD%E5%92%8C%E5%BC%82%E5%B8%B8%E7%9A%84%E5%A4%84%E7%90%86%E4%B8%8E%E6%8A%A2%E5%8D%A0%E5%BC%8F%E5%A4%9A%E4%BB%BB%E5%8A%A1/67c03f5323edfd9544c0235661096d39.png" class="">

<ol>
<li>首先临时保存段寄存器<strong>SS</strong>和栈指针<strong>ESP</strong>；</li>
<li>根据目标代码的特权级，从当前任务的<strong>TSS</strong>中选取一个栈段指针加载到栈指针<strong>ESP</strong>；</li>
<li>将选择的栈段选择子加载到段寄存器<strong>SS</strong>，将选择的栈指针加载到<strong>ESP</strong>；</li>
<li>切换到新栈，将刚才临时保存的段寄存器<strong>SS</strong>和栈指针<strong>ESP</strong>压入新栈；</li>
<li>接着将<strong>EFLAGS</strong>、<strong>CS</strong>、<strong>EIP</strong>压入新栈；</li>
<li>对于有错误代码的异常，处理器还要将错误代码压入新栈；</li>
<li>当中断返回时，要将<strong>EFLAGS</strong>、<strong>CS</strong>、<strong>EIP</strong>恢复，还将恢复原来的栈状态，即恢复之前临时保存的段寄存器<strong>SS</strong>和栈指针<strong>ESP</strong>；</li>
<li>恢复之后段寄存器依然指向旧栈段，栈指针寄存器<strong>ESP</strong>依然指向进入中断之前的位置。</li>
</ol>
<p>中断门和陷阱门的区别不大，通过中断门进入中断处理过程时，处理器先将<strong>EFLAGS</strong>压栈，再将其<strong>IF</strong>位清零以禁止嵌套的中断，即进入中断处理程序后不允许再响应别的中断。从中断返回时，将从栈中恢复<strong>EFLAGS</strong>的原始状态。</p>
<p>陷阱门的优先级较低，通过陷阱门进入中断处理过程时，<strong>EFLAGS</strong>的IF位不变，以允许其它中断优先处理。<strong>EFLAGS</strong>的<strong>IF</strong>位只影响硬件中断，不影响<strong>NMI</strong>、异常、INT形式的软中断。</p>
<p>错误代码格式：</p>
<img lazyload="" src="/images/loading.svg" data-src="/2022/12/11/30-%E4%B8%AD%E6%96%AD%E5%92%8C%E5%BC%82%E5%B8%B8%E7%9A%84%E5%A4%84%E7%90%86%E4%B8%8E%E6%8A%A2%E5%8D%A0%E5%BC%8F%E5%A4%9A%E4%BB%BB%E5%8A%A1/06739af9c2e734f283fc024ed041df76.png" class="">

<ul>
<li><strong>EXT位</strong>：1表示由<strong>NMI</strong>、硬件中断等引发；</li>
<li><strong>IDT位</strong>：1表示段选择子索引指向中断描述符<strong>IDT</strong>中的门描述符，0表示指向<strong>GDT</strong>、<strong>LDT</strong>中的描述符；</li>
<li><strong>TI位</strong>：表示指示器，当<strong>IDT</strong>位 = 0才有意义。0表示段选择子索引指向<strong>GDT</strong>，1表示指向<strong>LDT</strong>中的段描述符或门描述符；</li>
<li><strong>段选择子索引</strong>：用于指示<strong>GDT</strong>或<strong>LDT</strong>中的段描述符、或<strong>IDT</strong>内的门描述符。就是段选择子的高13位用于索引描述符。<img lazyload="" src="/images/loading.svg" data-src="/2022/12/11/30-%E4%B8%AD%E6%96%AD%E5%92%8C%E5%BC%82%E5%B8%B8%E7%9A%84%E5%A4%84%E7%90%86%E4%B8%8E%E6%8A%A2%E5%8D%A0%E5%BC%8F%E5%A4%9A%E4%BB%BB%E5%8A%A1/02c3a1acd2107868868cf3d50a36ffaa.png" class=""></li>
</ul>
<h2 id="11-在中断处理过程中实施任务切换（含NOP指令的介绍）"><a href="#11-在中断处理过程中实施任务切换（含NOP指令的介绍）" class="headerlink" title="11. 在中断处理过程中实施任务切换（含NOP指令的介绍）"></a>11. 在中断处理过程中实施任务切换（含NOP指令的介绍）</h2><p>接上一节，接着开放中断：</p>
<pre><code class="assembly">        sti			;开放硬件中断
</code></pre>
<p>假定在执行指令<mark>mov ebx, message_0<mark>时发生<strong>0x70号中断</strong>，这条指令完成后立即响应中断，用中断号0x70乘以8到中断描述符表中取出中断门进行特权级检查，然后进入<strong>0x70</strong>号中断的处理过程执行。</mark></mark></p>
<p>此时还没有创建内核任务，那么TR中的内容是无效的，因为<strong>0x70</strong>号中断的处理过程在内核公共例程段，特权级为0，当前特权级也是0，所以不需要切换栈，自然也不需要访问任务状态段<strong>TSS</strong>。</p>
<p><strong>0x70</strong>号中断的处理过程：</p>
<pre><code class="assembly">;-------------------------------------------------------------------------------
rtm_0x70_interrupt_handle:             ;实时时钟中断处理过程

    pushad
    
    mov al,0x20                        ;中断结束命令EOI
    out 0xa0,al                        ;向8259A从片发送
    out 0x20,al                        ;向8259A主片发送
    
    mov al,0x0c                        ;寄存器C的索引。且开放NMI
    out 0x70,al
    in al,0x71                         ;读一下RTC的寄存器C，否则只发生一次中断
               						   ;此处不考虑闹钟和周期性中断的情况
    ;请求任务调度
    call sys_routine_seg_sel:initiate_task_switch
    
    popad
    
    iretd
</code></pre>
<p>之后的内容为：</p>
<ul>
<li>显示处理器品牌信息；</li>
<li>安装调用门，对门进行测试；</li>
<li>创建内核任务相关，在创建之前使用<strong>cli</strong>指令清中断，之后<strong>sti</strong>指令开放中断；</li>
<li>创建第一个用户任务，在创建之前使用<strong>cli</strong>指令清中断，之后<strong>sti</strong>指令开放中断；<ol>
<li>在开放中断之后，若立即发生了<strong>0x70</strong>号中断，将执行任务切换，首先执行<mark>rtm_0x70_interrupt_handle</mark>，在里面先保存当前内核任务的状态到内核任务<strong>TSS</strong>中，接着将用户任务的状态从其<strong>TSS</strong>中恢复到处理器中，TR就指向用户任务，用户任务就成了当前任务。</li>
<li>第一次执行用户任务从入口点执行，先切换栈在死循环打印<mark>，，，，，，</mark>，在执行<mark>jmp .do_prn</mark>指令之前若发生了<strong>0x70</strong>号中断，又转到<mark>rtm_0x70_interrupt_handle</mark>执行；</li>
<li>这一次用户任务时当前任务，找到就绪的内核任务，先保存当前的任务也就是用户任务的状态到其<strong>TSS</strong>，然后将内核任务的状态从其<strong>TSS</strong>中恢复到处理器。此时<strong>TR</strong>指向内核任务，内核任务成为当前任务。内核任务从下面返回：<img lazyload="" src="/images/loading.svg" data-src="/2022/12/11/30-%E4%B8%AD%E6%96%AD%E5%92%8C%E5%BC%82%E5%B8%B8%E7%9A%84%E5%A4%84%E7%90%86%E4%B8%8E%E6%8A%A2%E5%8D%A0%E5%BC%8F%E5%A4%9A%E4%BB%BB%E5%8A%A1/b98070cf32d38af1095d692179618875.png" class=""></li>
</ol>
</li>
</ul>
<p>因为之前内核任务是从这里切换出去的，然后<strong>retf</strong>返回到中断处理过程<mark>rtm_0x70_interrupt_handle</mark>，如下：返回到<strong>popad</strong>指令处。</p>
<img lazyload="" src="/images/loading.svg" data-src="/2022/12/11/30-%E4%B8%AD%E6%96%AD%E5%92%8C%E5%BC%82%E5%B8%B8%E7%9A%84%E5%A4%84%E7%90%86%E4%B8%8E%E6%8A%A2%E5%8D%A0%E5%BC%8F%E5%A4%9A%E4%BB%BB%E5%8A%A1/5332d252c92ab03ba05f620d2d165454.png" class="">

<p>再执行<mark>iretd</mark>从中断处理过程返回到内核任务中上一次<strong>0x70</strong>号中断的地方，即内核<strong>start</strong>里面的nop指令处：</p>
<img lazyload="" src="/images/loading.svg" data-src="/2022/12/11/30-%E4%B8%AD%E6%96%AD%E5%92%8C%E5%BC%82%E5%B8%B8%E7%9A%84%E5%A4%84%E7%90%86%E4%B8%8E%E6%8A%A2%E5%8D%A0%E5%BC%8F%E5%A4%9A%E4%BB%BB%E5%8A%A1/7e6e29824e3d95591e20eeb190f3c945.png" class="">
<p>添加<strong>nop</strong>指令的意图是，假定在执行这三条<strong>nop</strong>指令期间发生了<strong>0x70</strong>号中断，于是处理器又一次在内核任务中中执行中断处理过程</p>
<p>之后顺序执行代码即可。</p>
<p>其中<strong>nop</strong>指令：</p>
<img lazyload="" src="/images/loading.svg" data-src="/2022/12/11/30-%E4%B8%AD%E6%96%AD%E5%92%8C%E5%BC%82%E5%B8%B8%E7%9A%84%E5%A4%84%E7%90%86%E4%B8%8E%E6%8A%A2%E5%8D%A0%E5%BC%8F%E5%A4%9A%E4%BB%BB%E5%8A%A1/61a9d56175641a5edbf7407f56f60a6a.png" class="">
<p>在调试期间，可能需要动态修改一个正在执行的程序，例如我们想把<mark>08 c9</mark>这条跳转指令去掉又不影响其它指令，此时最好的办法就是将其修改为<mark>90 90</mark>。</p>
<h2 id="12-抢占式多任务的执行效果演示"><a href="#12-抢占式多任务的执行效果演示" class="headerlink" title="12. 抢占式多任务的执行效果演示"></a>12. 抢占式多任务的执行效果演示</h2><p>接上一节，执行<strong>nop</strong>指令之后继续创建第二个用户任务：</p>
<pre><code class="assembly">    ;为说明任务切换而特意添加的无操作指令
    nop
    nop
    nop
    
    ;可以创建更多的任务，例如：
    cli
    mov ecx,0x46
    call sys_routine_seg_sel:allocate_memory
    mov word [es:ecx+0x04],0           ;任务状态：空闲
    call append_to_tcb_link            ;将此TCB添加到TCB链中
    
    push dword 100                     ;用户程序位于逻辑100扇区
    push ecx                           ;压入任务控制块起始线性地址
    
    call load_relocate_program
    sti
</code></pre>
<p>之后的内核任务是一个无限循环：</p>
<pre><code class="assembly">.do_switch:
    mov ebx,core_msg2
    call sys_routine_seg_sel:put_string
    
    ;清理已经终止的任务，并回收它们占用的资源
    call sys_routine_seg_sel:do_task_clean
    
    hlt
    
    jmp .do_switch
</code></pre>
<p>程序加载：</p>
<img lazyload="" src="/images/loading.svg" data-src="/2022/12/11/30-%E4%B8%AD%E6%96%AD%E5%92%8C%E5%BC%82%E5%B8%B8%E7%9A%84%E5%A4%84%E7%90%86%E4%B8%8E%E6%8A%A2%E5%8D%A0%E5%BC%8F%E5%A4%9A%E4%BB%BB%E5%8A%A1/5a7cfbe8d5a437a0aaf077939a037602.png" class="">
<p>虚拟机执行：</p>
<img lazyload="" src="/images/loading.svg" data-src="/2022/12/11/30-%E4%B8%AD%E6%96%AD%E5%92%8C%E5%BC%82%E5%B8%B8%E7%9A%84%E5%A4%84%E7%90%86%E4%B8%8E%E6%8A%A2%E5%8D%A0%E5%BC%8F%E5%A4%9A%E4%BB%BB%E5%8A%A1/b5657e47353d532e0cfe1989136f34ba.png" class="">
<img lazyload="" src="/images/loading.svg" data-src="/2022/12/11/30-%E4%B8%AD%E6%96%AD%E5%92%8C%E5%BC%82%E5%B8%B8%E7%9A%84%E5%A4%84%E7%90%86%E4%B8%8E%E6%8A%A2%E5%8D%A0%E5%BC%8F%E5%A4%9A%E4%BB%BB%E5%8A%A1/image-20221113165929743.png" class="" title="image-20221113165929743">


		</div>

		
		<div class="post-copyright-info w-full my-8 px-2 sm:px-6 md:px-8">
			<div class="article-copyright-info-container">
    <ul>
        <li><strong>标题:</strong> 中断和异常的处理与抢占式多任务</li>
        <li><strong>作者:</strong> xiaoeryu</li>
        <li><strong>创建于
                :</strong> 2022-12-11 22:48:00</li>
        
            <li>
                <strong>更新于
                    :</strong> 2023-10-03 13:00:20
            </li>
        
        <li>
            <strong>链接:</strong> https://github.com/xiaoeryu/2022/12/11/30-中断和异常的处理与抢占式多任务/
        </li>
        <li>
            <strong>
                版权声明:
            </strong>
            

            
                本文章采用 <a class="license" target="_blank" rel="noopener" href="https://creativecommons.org/licenses/by-nc-sa/4.0">CC BY-NC-SA 4.0</a> 进行许可。
            
        </li>
    </ul>
</div>

		</div>
		

		
		<ul class="post-tags-box text-lg mt-1.5 flex-wrap justify-center flex md:hidden">
			
			<li class="tag-item mx-0.5">
				<a href="/tags/x86%E4%B8%AD%E6%96%AD%E5%92%8C%E5%BC%82%E5%B8%B8/">#x86中断和异常</a>&nbsp;
			</li>
			
		</ul>
		

		

		
		<div class="article-nav my-8 flex justify-between items-center px-2 sm:px-6 md:px-8">
			
			<div class="article-prev border-border-color shadow-redefine-flat shadow-shadow-color-2 rounded-medium px-4 py-2 hover:shadow-redefine-flat-hover hover:shadow-shadow-color-2">
				<a class="prev" rel="prev" href="/2022/12/11/31-%E5%88%86%E9%A1%B5%E5%92%8C%E5%8A%A8%E6%80%81%E9%A1%B5%E9%9D%A2%E5%88%86%E9%85%8D/">
					<span class="left arrow-icon flex justify-center items-center">
						<i class="fa-solid fa-chevron-left"></i>
					</span>
					<span class="title flex justify-center items-center">
						<span class="post-nav-title-item">分页和动态页面分配</span>
						<span class="post-nav-item">上一篇</span>
					</span>
				</a>
			</div>
			
			
			<div class="article-next border-border-color shadow-redefine-flat shadow-shadow-color-2 rounded-medium px-4 py-2 hover:shadow-redefine-flat-hover hover:shadow-shadow-color-2">
				<a class="next" rel="next" href="/2022/12/11/29-%E5%8D%8F%E5%90%8C%E5%BC%8F%E4%BB%BB%E5%8A%A1%E5%88%87%E6%8D%A2/">
					<span class="title flex justify-center items-center">
						<span class="post-nav-title-item">协同式任务切换</span>
						<span class="post-nav-item">下一篇</span>
					</span>
					<span class="right arrow-icon flex justify-center items-center">
						<i class="fa-solid fa-chevron-right"></i>
					</span>
				</a>
			</div>
			
		</div>
		


		
		<div class="comment-container px-2 sm:px-6 md:px-8 pb-8">
			<div class="comments-container mt-10 w-full ">
    <div id="comment-anchor" class="w-full h-2.5"></div>
    <div class="comment-area-title w-full my-1.5 md:my-2.5 text-xl md:text-3xl font-bold">
        评论
    </div>
    

        
            


        
    
</div>

		</div>
		
	</div>

	
	<div class="toc-content-container">
		<div class="post-toc-wrap">
	<div class="post-toc">
		<div class="toc-title">目录</div>
		<div class="page-title">中断和异常的处理与抢占式多任务</div>
		<ol class="nav"><li class="nav-item nav-level-2"><a class="nav-link" href="#1-%E4%B8%AD%E6%96%AD%E5%92%8C%E5%BC%82%E5%B8%B8%E6%A6%82%E8%BF%B0"><span class="nav-text">1. 中断和异常概述</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#02-%E4%BF%9D%E6%8A%A4%E6%A8%A1%E5%BC%8F%E4%B8%8B%E4%B8%AD%E6%96%AD%E5%92%8C%E5%BC%82%E5%B8%B8%E7%9A%84%E5%90%91%E9%87%8F%E5%88%86%E9%85%8D"><span class="nav-text">02. 保护模式下中断和异常的向量分配</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#03-%E4%B8%AD%E6%96%AD%E6%8F%8F%E8%BF%B0%E7%AC%A6%E3%80%81%E4%B8%AD%E6%96%AD%E9%97%A8%E5%92%8C%E9%99%B7%E9%98%B1%E9%97%A8"><span class="nav-text">03. 中断描述符、中断门和陷阱门</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#04-%E6%9C%AC%E7%AB%A0%E7%A8%8B%E5%BA%8F%E4%BB%8B%E7%BB%8D"><span class="nav-text">04. 本章程序介绍</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#05-%E5%88%9B%E5%BB%BA%E5%B9%B6%E5%AE%89%E8%A3%85%E5%85%A8%E9%83%A8%E7%9A%84256%E4%B8%AA%E4%B8%AD%E6%96%AD%E9%97%A8"><span class="nav-text">05. 创建并安装全部的256个中断门</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#06-%E4%B8%BA%E5%AE%9E%E6%97%B6%E6%97%B6%E9%92%9F%E4%B8%AD%E6%96%AD%E5%88%9B%E5%BB%BA%E5%92%8C%E5%AE%89%E8%A3%85%E4%B8%AD%E6%96%AD%E9%97%A8"><span class="nav-text">06. 为实时时钟中断创建和安装中断门</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#07-%E5%8A%A0%E8%BD%BD%E4%B8%AD%E6%96%AD%E6%8F%8F%E8%BF%B0%E7%AC%A6%E8%A1%A8%E5%AF%84%E5%AD%98%E5%99%A8IDTR"><span class="nav-text">07. 加载中断描述符表寄存器IDTR</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#08-%E9%87%8D%E6%96%B0%E8%AE%BE%E7%BD%AE8259A%E4%B8%BB%E7%89%87%E7%9A%84%E4%B8%AD%E6%96%AD%E5%90%91%E9%87%8F"><span class="nav-text">08. 重新设置8259A主片的中断向量</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#09-%E4%B8%AD%E6%96%AD%E5%92%8C%E5%BC%82%E5%B8%B8%E5%8F%91%E7%94%9F%E4%BC%BC%E7%9A%84%E7%89%B9%E6%9D%83%E7%BA%A7%E6%A3%80%E6%9F%A5"><span class="nav-text">09. 中断和异常发生似的特权级检查</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#10-%E4%B8%AD%E6%96%AD%E5%92%8C%E5%BC%82%E5%B8%B8%E5%8F%91%E7%94%9F%E6%97%B6%E7%9A%84%E6%A0%88%E5%88%87%E6%8D%A2%E8%BF%87%E7%A8%8B"><span class="nav-text">10. 中断和异常发生时的栈切换过程</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#11-%E5%9C%A8%E4%B8%AD%E6%96%AD%E5%A4%84%E7%90%86%E8%BF%87%E7%A8%8B%E4%B8%AD%E5%AE%9E%E6%96%BD%E4%BB%BB%E5%8A%A1%E5%88%87%E6%8D%A2%EF%BC%88%E5%90%ABNOP%E6%8C%87%E4%BB%A4%E7%9A%84%E4%BB%8B%E7%BB%8D%EF%BC%89"><span class="nav-text">11. 在中断处理过程中实施任务切换（含NOP指令的介绍）</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#12-%E6%8A%A2%E5%8D%A0%E5%BC%8F%E5%A4%9A%E4%BB%BB%E5%8A%A1%E7%9A%84%E6%89%A7%E8%A1%8C%E6%95%88%E6%9E%9C%E6%BC%94%E7%A4%BA"><span class="nav-text">12. 抢占式多任务的执行效果演示</span></a></li></ol>

	</div>
</div>
	</div>
	
</div>
			</div>

			
		</div>

		<div class="main-content-footer">
			<footer class="footer mt-5 py-5 h-auto text-base text-third-text-color relative border-t-2 border-t-border-color">
    <div class="info-container py-3 text-center">
        
        <div class="text-center">
            &copy;
            
              <span>2022</span>
              -
            
            2025&nbsp;&nbsp;<i class="fa-solid fa-heart fa-beat" style="--fa-animation-duration: 0.5s; color: #f54545"></i>&nbsp;&nbsp;<a href="/">xiaoeryu</a>
            
                
                <p class="post-count space-x-0.5">
                    <span>
                        共撰写了 112 篇文章
                    </span>
                    
                </p>
            
        </div>
        
            <script data-swup-reload-script src="https://busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js"></script>
            <div class="relative text-center lg:absolute lg:right-[20px] lg:top-1/2 lg:-translate-y-1/2 lg:text-right">
                
                    <span id="busuanzi_container_site_uv" class="lg:!block">
                        <span class="text-sm">访问人数</span>
                        <span id="busuanzi_value_site_uv"></span>
                    </span>
                
                
                    <span id="busuanzi_container_site_pv" class="lg:!block">
                        <span class="text-sm">总访问量</span>
                        <span id="busuanzi_value_site_pv"></span>
                    </span>
                
            </div>
        
        <div class="relative text-center lg:absolute lg:left-[20px] lg:top-1/2 lg:-translate-y-1/2 lg:text-left">
            <span class="lg:block text-sm">由 <?xml version="1.0" encoding="utf-8"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg class="relative top-[2px] inline-block align-baseline" version="1.1" id="圖層_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="1rem" height="1rem" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve"><path fill="#0E83CD" d="M256.4,25.8l-200,115.5L56,371.5l199.6,114.7l200-115.5l0.4-230.2L256.4,25.8z M349,354.6l-18.4,10.7l-18.6-11V275H200v79.6l-18.4,10.7l-18.6-11v-197l18.5-10.6l18.5,10.8V237h112v-79.6l18.5-10.6l18.5,10.8V354.6z"/></svg><a target="_blank" class="text-base" href="https://hexo.io">Hexo</a> 驱动</span>
            <span class="text-sm lg:block">主题&nbsp;<a class="text-base" target="_blank" href="https://github.com/EvanNotFound/hexo-theme-redefine">Redefine v2.8.2</a></span>
        </div>
        
        
            <div>
                博客已运行 <span class="odometer" id="runtime_days" ></span> 天 <span class="odometer" id="runtime_hours"></span> 小时 <span class="odometer" id="runtime_minutes"></span> 分钟 <span class="odometer" id="runtime_seconds"></span> 秒
            </div>
        
        
            <script data-swup-reload-script>
                try {
                    function odometer_init() {
                    const elements = document.querySelectorAll('.odometer');
                    elements.forEach(el => {
                        new Odometer({
                            el,
                            format: '( ddd).dd',
                            duration: 200
                        });
                    });
                    }
                    odometer_init();
                } catch (error) {}
            </script>
        
        
        
    </div>  
</footer>
		</div>
	</div>

	
	<div class="post-tools">
		<div class="post-tools-container">
	<ul class="article-tools-list">
		<!-- TOC aside toggle -->
		
		<li class="right-bottom-tools page-aside-toggle">
			<i class="fa-regular fa-outdent"></i>
		</li>
		

		<!-- go comment -->
		
		<li class="go-comment">
			<i class="fa-regular fa-comments"></i>
		</li>
		
	</ul>
</div>
	</div>
	

	<div class="right-side-tools-container">
		<div class="side-tools-container">
	<ul class="hidden-tools-list">
		<li class="right-bottom-tools tool-font-adjust-plus flex justify-center items-center">
			<i class="fa-regular fa-magnifying-glass-plus"></i>
		</li>

		<li class="right-bottom-tools tool-font-adjust-minus flex justify-center items-center">
			<i class="fa-regular fa-magnifying-glass-minus"></i>
		</li>

		<li class="right-bottom-tools tool-dark-light-toggle flex justify-center items-center">
			<i class="fa-regular fa-moon"></i>
		</li>

		<!-- rss -->
		

		

		<li class="right-bottom-tools tool-scroll-to-bottom flex justify-center items-center">
			<i class="fa-regular fa-arrow-down"></i>
		</li>
	</ul>

	<ul class="visible-tools-list">
		<li class="right-bottom-tools toggle-tools-list flex justify-center items-center">
			<i class="fa-regular fa-cog fa-spin"></i>
		</li>
		
		<li class="right-bottom-tools tool-scroll-to-top flex justify-center items-center">
			<i class="arrow-up fas fa-arrow-up"></i>
			<span class="percent"></span>
		</li>
		
		
	</ul>
</div>
	</div>

	<div class="image-viewer-container">
	<img src="">
</div>

	
	<div class="search-pop-overlay">
	<div class="popup search-popup">
		<div class="search-header">
			<span class="search-input-field-pre">
				<i class="fa-solid fa-keyboard"></i>
			</span>
			<div class="search-input-container">
				<input autocomplete="off" autocorrect="off" autocapitalize="off" placeholder="站内搜索您需要的内容..." spellcheck="false" type="search" class="search-input">
			</div>
			<span class="popup-btn-close">
				<i class="fa-solid fa-times"></i>
			</span>
		</div>
		<div id="search-result">
			<div id="no-result">
				<i class="fa-solid fa-spinner fa-spin-pulse fa-5x fa-fw"></i>
			</div>
		</div>
	</div>
</div>
	

</main>



<script src="/js/build/libs/Swup.min.js"></script>

<script src="/js/build/libs/SwupSlideTheme.min.js"></script>

<script src="/js/build/libs/SwupScriptsPlugin.min.js"></script>

<script src="/js/build/libs/SwupProgressPlugin.min.js"></script>

<script src="/js/build/libs/SwupScrollPlugin.min.js"></script>

<script src="/js/build/libs/SwupPreloadPlugin.min.js"></script>

<script>
    const swup = new Swup({
        plugins: [
            new SwupScriptsPlugin({
                optin: true,
            }),
            new SwupProgressPlugin(),
            new SwupScrollPlugin({
                offset: 80,
            }),
            new SwupSlideTheme({
                mainElement: ".main-content-body",
            }),
            new SwupPreloadPlugin(),
        ],
        containers: ["#swup"],
    });
</script>




	
<script src="/js/build/tools/imageViewer.js" type="module"></script>

<script src="/js/build/utils.js" type="module"></script>

<script src="/js/build/main.js" type="module"></script>

<script src="/js/build/layouts/navbarShrink.js" type="module"></script>

<script src="/js/build/tools/scrollTopBottom.js" type="module"></script>

<script src="/js/build/tools/lightDarkSwitch.js" type="module"></script>

<script src="/js/build/layouts/categoryList.js" type="module"></script>



    
<script src="/js/build/tools/localSearch.js" type="module"></script>




    
<script src="/js/build/tools/codeBlock.js" type="module"></script>




    
<script src="/js/build/layouts/lazyload.js" type="module"></script>




    
<script src="/js/build/tools/runtime.js"></script>

    
<script src="/js/build/libs/odometer.min.js"></script>

    
<link rel="stylesheet" href="/assets/odometer-theme-minimal.css">




  
<script src="/js/build/libs/Typed.min.js"></script>

  
<script src="/js/build/plugins/typed.js" type="module"></script>








    
<script src="/js/build/libs/anime.min.js"></script>





    
<script src="/js/build/tools/tocToggle.js" type="module" data-swup-reload-script=""></script>

<script src="/js/build/layouts/toc.js" type="module" data-swup-reload-script=""></script>

<script src="/js/build/plugins/tabs.js" type="module" data-swup-reload-script=""></script>




<script src="/js/build/libs/moment-with-locales.min.js" data-swup-reload-script=""></script>


<script src="/js/build/layouts/essays.js" type="module" data-swup-reload-script=""></script>





	
</body>

</html>